package com.comtop.topcloud.device.util;

import cn.hutool.core.util.StrUtil;
import com.comtop.topcloud.device.enums.TimeGranularity;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

public class TimeUtils {

    public static Date getPreviousTime(TimeGranularity timeGranularity, Date currentDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);

        switch (timeGranularity) {
            case HOUR:
                // 将当前时间减去1小时
                calendar.add(Calendar.HOUR_OF_DAY, -1);
                break;
            case DAY:
                // 将当前时间减去1天
                calendar.add(Calendar.DATE, -1);
                break;
            case MONTH:
                // 将当前时间减去1个月
                calendar.add(Calendar.MONTH, -1);
                break;
            case MINUTE:
                // 将当前时间减去1分钟
                calendar.add(Calendar.MINUTE, -1);
                break;
            default:
                throw new IllegalArgumentException("不支持的时间粒度");
        }

        return calendar.getTime();
    }

    /**
     * 获取上一个时间段的开始和结束时间戳
     * 根据当前时间粒度计算上一个完整时间段
     *
     * @param timeGranularity 时间粒度（如：HOUR, MINUTE）
     * @return 包含开始时间戳和结束时间戳的数组 [startTimestamp, endTimestamp]
     */
    public static long[] getPreviousTimeRange(TimeGranularity timeGranularity) {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;

        switch (timeGranularity) {
            case MINUTE:
                // 计算上一个分钟的开始和结束时间
                int minute = now.getMinute();
                int minutesToSubtract = minute % 15; // 获取当前时间离最近的15分钟区间的偏差

                startDateTime = now.minusMinutes(minutesToSubtract) // 回到最近的15分钟区间的起始点
                        .withSecond(0)  // 设置秒为0
                        .withNano(0);   // 设置纳秒为0

                endDateTime = startDateTime.plusMinutes(14)  // 结束时间是起始时间的15分钟后
                        .withSecond(59)  // 设置秒为59
                        .withNano(999999999);  // 设置纳秒为最大值，表示结束的最后一刻
                break;
            case HOUR:
                // 计算上一个小时的开始和结束时间
                startDateTime = now.minusHours(1).withMinute(0).withSecond(0).withNano(0); // 上一小时的开始
                endDateTime = now.minusHours(1).withMinute(59).withSecond(59).withNano(0); // 上一小时的结束
                break;

            case DAY:
                // 计算昨天的开始和结束时间
                startDateTime = now.minusDays(1).toLocalDate().atStartOfDay(); // 昨天0点开始
                endDateTime = now.minusDays(1).toLocalDate().atTime(23, 59, 59); // 昨天23:59:59结束
                break;

            case MONTH:
                // 计算上个月的开始和结束时间
                startDateTime = now.minusMonths(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0); // 上个月1号0点
                endDateTime = now.minusMonths(1).withDayOfMonth(now.minusMonths(1).toLocalDate().lengthOfMonth()).withHour(23).withMinute(59).withSecond(59); // 上个月最后一天23:59:59
                break;

            case YEAR:
                // 计算去年开始和结束时间
                startDateTime = now.minusYears(1).withMonth(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0); // 去年1月1日0点
                endDateTime = now.minusYears(1).withMonth(12).withDayOfMonth(31).withHour(23).withMinute(59).withSecond(59); // 去年12月31日23:59:59
                break;
        }

        // 转换为时间戳（秒级）
        long startTimestamp = startDateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
        long endTimestamp = endDateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();

        return new long[]{startTimestamp, endTimestamp};
    }

    /**
     * 计算从上次统计到当前时间之间的统计次数
     * 根据时间粒度（如：分钟、小时、天、月、年）和当前时间计算差值
     *
     * @param lastTimestamp    上次统计的时间
     * @param currentTimestamp 当前时间
     * @param timeGranularity  时间粒度（如：MINUTE, HOUR, DAY, MONTH, YEAR）
     * @return 需要统计的次数
     */
    public static int calculateMissingStatisticsCount(Date currentTimestamp, Date lastTimestamp, TimeGranularity timeGranularity) {
        // 获取时间差，单位为毫秒
        long timeDiff = currentTimestamp.getTime() - lastTimestamp.getTime();

        switch (timeGranularity) {
            case MINUTE:
                // 如果粒度是分钟，计算分钟差，注意：因为时间差是毫秒，转换成分钟差
                return (int) (timeDiff / (60 * 1000));
            case HOUR:
                // 如果粒度是小时，计算小时差，转换成小时差
                return (int) (timeDiff / (60 * 60 * 1000));
            case DAY:
                // 如果粒度是天，计算天数差，转换成天数差
                return (int) (timeDiff / (24 * 60 * 60 * 1000));
            case MONTH:
                // 计算月份差
                return calculateMonthDifference(lastTimestamp, currentTimestamp);
            case YEAR:
                // 计算年份差
                return calculateYearDifference(lastTimestamp, currentTimestamp);
            default:
                throw new IllegalArgumentException("Unsupported TimeGranularity: " + timeGranularity);
        }
    }

    /**
     * 计算上次统计和当前时间之间的完整月份差
     *
     * @param lastTimestamp    上次统计的时间
     * @param currentTimestamp 当前时间
     * @return 完整的月份差
     */
    private static int calculateMonthDifference(Date lastTimestamp, Date currentTimestamp) {
        LocalDate lastDate = toLocalDate(lastTimestamp);
        LocalDate currentDate = toLocalDate(currentTimestamp);

        int yearsDiff = currentDate.getYear() - lastDate.getYear();
        int monthsDiff = currentDate.getMonthValue() - lastDate.getMonthValue();

        // 将年份差转换为月差并加上当前的月差
        return yearsDiff * 12 + monthsDiff;
    }

    /**
     * 计算上次统计和当前时间之间的完整年份差
     *
     * @param lastTimestamp    上次统计的时间
     * @param currentTimestamp 当前时间
     * @return 完整的年份差
     */
    private static int calculateYearDifference(Date lastTimestamp, Date currentTimestamp) {
        LocalDate lastDate = toLocalDate(lastTimestamp);
        LocalDate currentDate = toLocalDate(currentTimestamp);

        return currentDate.getYear() - lastDate.getYear();
    }

    /**
     * 将 Date 转换为 LocalDate
     *
     * @param date Date 对象
     * @return LocalDate 对象
     */
    private static LocalDate toLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static String formatByLocalDateTimeFormat(LocalDateTime localDateTime, String format) {
        String result = StrUtil.EMPTY;
        if (localDateTime != null) {
            try {
                DateTimeFormatter sdf = DateTimeFormatter.ofPattern(format);
                result = sdf.format(localDateTime);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
}
